// ProgressDlg.cpp : implementation file
//

#include "stdafx.h"
#include "RGD.h"
#include "ProgressDlg.h"


// CProgressDlg dialog

IMPLEMENT_DYNAMIC(CProgressDlg, CDialog)

CProgressDlg::CProgressDlg(Problem *p, bool showMessage, CWnd* pParent /*=NULL*/)
	: CDialog(CProgressDlg::IDD, pParent)
	, m_problem(p)
	, m_solvingStartTime(0)
	, m_bShowMessage(showMessage)
{

}

CProgressDlg::~CProgressDlg()
{
}

void CProgressDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
}


BEGIN_MESSAGE_MAP(CProgressDlg, CDialog)
	ON_WM_TIMER()
END_MESSAGE_MAP()


// CProgressDlg message handlers
void CProgressDlg::onStepCompleated(gdScalar time, gdScalar totalTime, unsigned int numTimesteps)
{
	setProgress(time, totalTime, numTimesteps);
}

struct SolveParams
{
	gdScalar time;
	Problem *pr;
	std::string fileName;
};

DWORD WINAPI MyThreadFunction( LPVOID lpParam )
{
	SolveParams* params = static_cast<SolveParams*>(lpParam);
	params->pr->solve(params->time, params->fileName);

	return 0;
}

void CProgressDlg::solve(gdScalar time, const std::string& fileName)
{
	SolveParams params;
	params.pr = m_problem;
	params.time = time;
	params.fileName = fileName;
	CreateThread( 
		NULL,                   // default security attributes
		0,                      // use default stack size  
		MyThreadFunction,       // thread function name
		&params,          // argument to thread function 
		0,                      // use default creation flags 
		NULL);   // returns the thread identifier 

	m_solvingStartTime = GetTickCount64();

	DoModal();

//	m_problem->setListener(NULL);
}

void CProgressDlg::setProgress(gdScalar time, gdScalar totalTime, unsigned int numTimesteps)
{
	CProgressCtrl *pr = static_cast<CProgressCtrl*>(GetDlgItem(IDC_PROGRESS));
	_ASSERT(pr != NULL);
	gdScalar progress = time / totalTime;
	gdScalar pos = progress * gdScalar(1000.0);
	pr->SetPos(int(pos));

	// Update statistics
	CWnd* pLabel = GetDlgItem(IDC_STATISTICS);
	TCHAR buf[1024];
	ULONGLONG curTime = GetTickCount64();
	unsigned int solveTime = (unsigned int)(curTime - m_solvingStartTime);
	unsigned int timeLeft = 0;
	if (time < totalTime)
		timeLeft = (unsigned int)(gdScalar(solveTime) * ((totalTime - time) / time));

	_stprintf(buf, _T("Model Time: %f/%f; Solving time: %02d:%02d:%02d; Estimate time left: %02d:%02d:%02d; Timesteps: %d"),
		time, totalTime, solveTime / 60 / 60000, (solveTime / 60000) % 60, (solveTime / 1000) % 60,
		timeLeft / 60 / 60000, (timeLeft / 60000) % 60, (timeLeft / 1000) % 60, numTimesteps);
	pLabel->SetWindowText(buf);
}

BOOL CProgressDlg::OnInitDialog()
{
	__super::OnInitDialog();

	SetTimer(1, 50, NULL);

	CProgressCtrl *pr = static_cast<CProgressCtrl*>(GetDlgItem(IDC_PROGRESS));
	_ASSERT(pr != NULL);
	pr->SetRange(0, 1000);
	setProgress(gdScalar(0.0), gdScalar(1.0), 0);

	m_problem->setListener(this);

	return TRUE;  // return TRUE unless you set the focus to a control
	// EXCEPTION: OCX Property Pages should return FALSE
}

void CProgressDlg::OnOK()
{
	// TODO: Add your specialized code here and/or call the base class

//	__super::OnOK();
}

void CProgressDlg::OnCancel()
{
	// TODO: Add your specialized code here and/or call the base class

//	__super::OnCancel();
}

void CProgressDlg::OnTimer(UINT_PTR nIDEvent)
{
	CProgressCtrl *pr = static_cast<CProgressCtrl*>(GetDlgItem(IDC_PROGRESS));
	_ASSERT(pr != NULL);
	if (pr->GetPos() >= 1000)
	{
		KillTimer(1);

		// Show statistics
		TCHAR buf[1024];
		ULONGLONG curTime = GetTickCount64();
		unsigned int solveTime = (unsigned int)(curTime - m_solvingStartTime);
		_stprintf(buf, _T("Solving time: %02d:%02d:%02d; Timesteps: %d"),
			solveTime / 60 / 60000, (solveTime / 60000) % 60, (solveTime / 1000) % 60, m_problem->getNumSteps());
		if (m_bShowMessage)
			MessageBox(buf, _T("Statistics"), MB_OK | MB_ICONINFORMATION);

		CDialog::OnCancel();
	}

	__super::OnTimer(nIDEvent);
}
